package com.ztesoft.web.syncbaseinfo.service.impl;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ztesoft.core.cache.EhCacheService;
import com.ztesoft.core.spring.cache.StringKeyGenerator;
import com.ztesoft.framework.exception.BaseAppException;
import com.ztesoft.framework.exception.ExceptionHandler;
import com.ztesoft.framework.log.ZTEsoftLogManager;
import com.ztesoft.framework.util.DateUtils;
import com.ztesoft.framework.util.StringUtils;
import com.ztesoft.framework.util.Utils;
import com.ztesoft.iocp.cipher.util.RSAUtils;
import com.ztesoft.iocp.dto.DataSyncPO;
import com.ztesoft.iocp.utils.HttpUtils;
import com.ztesoft.web.baseconfig.db.dao.TargetColMapDao;
import com.ztesoft.web.baseconfig.db.po.DmPlanPO;
import com.ztesoft.web.baseconfig.db.po.TargetColMapPO;
import com.ztesoft.web.common.DMSConstant;
import com.ztesoft.web.common.ErrorCode;
import com.ztesoft.web.common.Util;
import com.ztesoft.web.common.customdb.dao.DbBaseInfoCustomDao;
import com.ztesoft.web.common.customdb.dao.DbLinkInstanceCustomDao;
import com.ztesoft.web.common.customdb.dao.DmHostConnInfoCustomDao;
import com.ztesoft.web.common.customdb.dao.DmTaskStageCustomDao;
import com.ztesoft.web.common.customdb.dao.EnumListCustomDao;
import com.ztesoft.web.common.customdb.dao.SysModuleCustomDao;
import com.ztesoft.web.common.customdb.dao.dto.DmTaskStageDto;
import com.ztesoft.web.common.customdb.dao.dto.SysModuleDto;
import com.ztesoft.web.common.db.arg.DmHostConnInfoArg;
import com.ztesoft.web.common.db.dao.DmHostConnInfoDao;
import com.ztesoft.web.common.db.po.DmHostConnInfoPO;
import com.ztesoft.web.common.vo.DbBaseInfoVO;
import com.ztesoft.web.common.vo.DbLinkInstanceVO;
import com.ztesoft.web.common.vo.DbUserInfoVO;
import com.ztesoft.web.common.vo.HostConnInfoVO;
import com.ztesoft.web.common.vo.TaskNotify;
import com.ztesoft.web.syncbaseinfo.service.BaseInfoService;
import com.ztesoft.web.taskgenerator.db.arg.DmTaskArg;
import com.ztesoft.web.taskgenerator.db.dao.DmTaskDao;
import com.ztesoft.web.taskgenerator.db.po.DmTaskPO;



/**
 * @Description 
 * @author lin.weibin@zte.com.cn
 * @date 2015年8月6日 下午8:21:02
 * @since 1.0
 *
 */
/**
 * 
 * 
 * @author lin.weibin@zte.com.cn
 * @date 2015年9月14日
 * @since 1.0
 */
@Service
public class BaseInfoServiceImpl implements BaseInfoService{

    private final static ZTEsoftLogManager LOGGER = ZTEsoftLogManager
            .getLogger(BaseInfoServiceImpl.class);
    
	@Autowired
	private SysModuleCustomDao sysModuleDao;
	
    @Resource(name = "frameworkEhCacheService")
    private EhCacheService dmsCacheService;
    
    @Resource(name = "stringKeyGenerator")
    private StringKeyGenerator stringKeyGenerator;

    @Autowired
    private EnumListCustomDao enumListCustomDao;
    
    @Autowired
    private DmTaskStageCustomDao taskStageCustomDao;
    
    @Autowired
    private DbBaseInfoCustomDao dbBaseInfoDao;
    
	@Autowired
	private DmTaskDao taskDao;

    @Autowired
    private DbLinkInstanceCustomDao dbLinkInstanceDao;
    
    @Autowired
    private DmHostConnInfoCustomDao dmHostConnInfoCustomDao;
    
	@Autowired
	private TargetColMapDao targetColMapDao;
	
	@Autowired
	private DmHostConnInfoDao dmHostConnInfoDao;
	
	public int getColumnType(int sourceDataId, String columnName) throws BaseAppException {
		Object columnType = dmsCacheService.get("dmsCache", "getColumnType"+sourceDataId+columnName);
		if (columnType == null) {
//			Map<String, Integer> map = new HashMap<String, Integer>();
			List<TargetColMapPO> list = targetColMapDao.selectSourceColumn(sourceDataId);
			for (TargetColMapPO colMapPO : list) {
				dmsCacheService.put("dmsCache", "getColumnType"+sourceDataId+colMapPO.getSourceColumn(), colMapPO.getSourceColumnType());
//				System.out.println("========for key="+"getColumnType"+sourceDataId+colMapPO.getSourceColumn()+"====value="+colMapPO.getSourceColumnType());
//				map.put(colMapPO.getSourceColumn(), colMapPO.getSourceColumnType());
			}
			columnType = dmsCacheService.get("dmsCache", "getColumnType"+sourceDataId+columnName);
		}
		if (columnType == null) {
			throw ExceptionHandler.publish("", "|查询target_col_map表获取ColumnType失败|sourceDataId="+sourceDataId+",columnName="+columnName);
		}
		return (Integer)columnType;
	}
	
    /**
     * 获取获取系统模板类LEVEL为0记录信息
     * @param moduleId
     * @return	系统模板对象
     */
	public int getRootLevelSysModule(int moduleId) {
		LOGGER.info("|获取获取系统模板类LEVEL为0记录信息|");
		Map<Integer, SysModuleDto> map;
		List<SysModuleDto> list = sysModuleDao.selectSysModule();
		if (!Utils.isEmpty(list)) {
			map = new HashMap<Integer, SysModuleDto>();
			for (SysModuleDto dto : list) {
				map.put(dto.getModuleId(), dto);
			}
			while (map.get(moduleId).getModuleLevel() !=0) {
				moduleId = map.get(moduleId).getParentModuleId();
			}
			return moduleId;
		} else {
			return -1;
		}
    }
    
	/**
	 * 请求同步主机数据信息
	 * @param hostId	null/value
	 */
	public void addHostBaseInfo(Integer hostId) {
		try {
			LOGGER.info(new StringBuilder("请求同步主机数据信息__IP_: [").append(InetAddress.getLocalHost())
					.append("] --hostId:").append(hostId).append(":time:")
					.append(DateUtils.getCurrentDate())
					.toString());
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		}
		if (hostId == null) dmHostConnInfoCustomDao.deleteByPrimaryKey(hostId);
		DataSyncPO req = new DataSyncPO();
		req.setHostId(hostId);
		req.setRequestType("HostInfo");
		req.setSubSystemId(com.ztesoft.web.common.Configuration.getInt("SUB_SYSTEM_ID"));
		String response = "";
		try {
			response = HttpUtils.getDataByUrl(
					com.ztesoft.iocp.common.Configuration.getString("baseURL")
							+ "/hostInfo/queryHost.do", req.toUrlParams());
		} catch (Exception e) {
			LOGGER.error("链接异常\r\n"+com.ztesoft.iocp.common.Configuration.getString("baseURL")+"/hostInfo/queryHost.do",e
					);
			return;
		}
		JSONObject json = JSONObject.parseObject(response);
		String content = json.get("Content").toString();
		LOGGER.info("content:"+content);
		if (content.contains("<![CDATA[")) {
			content = content.substring(9, content.length()-3);
			dmsCacheService.evict("dmsCache", "HostInfo" + hostId);
			if (null == content || "null".equals(content)) {
				LOGGER.error("同步信息为空:"+content);
				return;
			}
		} else {
			LOGGER.error("同步主机信息失败:"+content);
			return;
		}
		JSONArray contentJSON = JSONObject.parseArray(content);
		if (contentJSON.size() == 0) {
			LOGGER.error("获取不到"+(hostId == null ? "所有" : "hostId="+hostId)+"主机信息");
			return;
		}
		List<HostConnInfoVO> hosts = new ArrayList<HostConnInfoVO>();
		HostConnInfoVO vo;
		zte: for (int i = 0; i < contentJSON.size(); i++) {
			vo = JSON.toJavaObject(contentJSON.getJSONObject(i),HostConnInfoVO.class);
			if (Utils.isEmpty(vo.getHostConnMethod())) {//过滤。。
				LOGGER.error("过滤数据信息不完整hostId="+hostId);
				continue zte;
			}
			dmsCacheService.put("dmsCache", "HostInfo"+vo.getHostId(), vo);
			dmsCacheService.put("dmsCache", "HostInfo"+vo.getIp(), vo);
			hosts.add(vo);
		}
		dmHostConnInfoCustomDao.deleteByPrimaryKey(hostId);
		dmHostConnInfoCustomDao.insertBatch(hosts);
		LOGGER.info("end ...");
	}
	
	/**
	 * 删除主机信息和缓存
	 * @param hostId
	 */
	public void deleteHostInfo(Integer hostId) {
		LOGGER.info(new StringBuilder("删除主机信息和缓存").append(":time:")
				.append(DateUtils.getCurrentDate()).toString());
		dmHostConnInfoCustomDao.deleteByPrimaryKey(hostId);
		dmsCacheService.evict("dmsCache", "HostInfo" + hostId);
	}
	
	public void addDBBaseInfo(Integer dbBaseId) {
		try {
			LOGGER.info(new StringBuilder("请求数据库信息__IP_: [").append(InetAddress.getLocalHost())
					.append("] --dbBaseId:").append(dbBaseId).append(":time:")
					.append(DateUtils.getCurrentDate())
					.toString());
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		}
		if(dbBaseId == null) deleteDBInfo(dbBaseId);
		DataSyncPO req = new DataSyncPO();
		req.setDbBaseId(dbBaseId);//数据库基本信息标志
		req.setRequestType("DBInfo");//可有可无
		req.setSubSystemId(com.ztesoft.web.common.Configuration.getInt("SUB_SYSTEM_ID"));
		String response = "";
		String url = "";
		try {
			url = com.ztesoft.iocp.common.Configuration.getString("baseURL") + "/dbInfo/queryDBLink.do";
			LOGGER.info("请求地址：{0}",url);
			response = HttpUtils.getDataByUrl(url, req.toUrlParams());
		} catch (Exception e) {
			LOGGER.error("链接异常:"+url,e);
			return;
		}
		JSONObject json = JSONObject.parseObject(response);
		String content = json.get("Content").toString();
		LOGGER.info("content:"+content);
		if (content.contains("<![CDATA[")) {
			content = content.substring(9, content.length()-3);
			deleteDBInfo(dbBaseId);
			if (null == content || "null".equals(content)) {
				LOGGER.error("同步数据库信息为空:"+content);
				return;
			}
		} else {
			LOGGER.error("同步数据库信息失败:"+content);
			return;
		}
		JSONArray contentJSON = JSONObject.parseArray(content);
		if (Utils.isEmpty(contentJSON)) {
			LOGGER.error("获取不到"+(dbBaseId == null ? "所有" : "dbBaseId="+dbBaseId)+"数据库信息");
			return;
		}
//		List<DbBaseInfoVO> baseInfos = new ArrayList<DbBaseInfoVO>();
		List<DbLinkInstanceVO> dbInstanceList =null;
		List<DbLinkInstanceVO> dbInstanceNewList = null;
		List<DbUserInfoVO> dbUserInfoList = null;
		List<DbUserInfoVO> dbUserInfoNewList = null;
		DbBaseInfoVO vo;
		sync: for (int i = 0; i < contentJSON.size(); i++) {//数据库基本信息
			vo = JSON.toJavaObject(contentJSON.getJSONObject(i),DbBaseInfoVO.class);
			if ("00A".equals(vo.getState()) && Utils.notEmpty(vo.getDbLinkInstance())) {//00A且不空
//				baseInfos.add(vo);
				dbInstanceList = vo.getDbLinkInstance();
				dbInstanceNewList = new ArrayList<DbLinkInstanceVO>();
				for (int j = 0; j < dbInstanceList.size(); j++) {//数据库实例信息
					DbLinkInstanceVO dbInstanceVO = dbInstanceList.get(j);
					if ("00A".equals(dbInstanceVO.getState())&& Utils.notEmpty(dbInstanceVO.getDbUserInfo())) {//						
						dbInstanceNewList.add(dbInstanceVO);
						dbUserInfoList = dbInstanceVO.getDbUserInfo();
						dbUserInfoNewList = new ArrayList<DbUserInfoVO>();
						for (DbUserInfoVO dbUserInfo : dbUserInfoList) {//数据库用户信息
							if ("00A".equals(dbInstanceVO.getState())&& Utils.notEmpty(dbInstanceVO.getDbUserInfo())) {//
								dbUserInfoNewList.add(dbUserInfo);
								dmsCacheService.put("dmsCache", 
										"DbUserInfo"+dbInstanceVO.getDbLinkId()+dbUserInfo.getDbUserName(), dbUserInfo);
							}
						}
					}
					//
					if (Utils.notEmpty(dbUserInfoNewList)) {						
						dmsCacheService.put("dmsCache", 
								"DBInstanceInfo"+dbInstanceVO.getDbLinkId(), dbInstanceVO);
					}
				}
				if (Utils.isEmpty(dbInstanceNewList) || Utils.isEmpty(dbUserInfoNewList)) {
					LOGGER.error("过滤数据信息不完整DbBaseID="+vo.getDbBaseId());
					continue sync;
				}
				dmsCacheService.put("dmsCache", "DbBaseInfo"+vo.getDbBaseId(), vo);
				dbBaseInfoDao.insert(vo);
				dbLinkInstanceDao.insertBatch(dbInstanceNewList);
			}
		}
		LOGGER.info("request sync end ...");
	}

	public void deleteDBInfo(Integer dbBaseId) {
		LOGGER.info("删除数据库数据dbBaseId:"+dbBaseId);
		dmsCacheService.evict("dmsCache", "DbBaseInfo" + dbBaseId);
		dbLinkInstanceDao.deleteByDbBaseId(dbBaseId);
		dbBaseInfoDao.deleteByPrimaryKey(dbBaseId);
	}
	
	/**
	 * 数据库信息、连接方式——公共查询方法
	 */
	@Override
	public DbBaseInfoVO queryDBInfo(Integer dbBaseId) throws BaseAppException {
		DbBaseInfoVO dbBaseInfo = (DbBaseInfoVO) dmsCacheService.get("dmsCache", "DbBaseInfo"+dbBaseId);
		
//		if (obj == null) {
//			addDBBaseInfo(dbBaseId);
//			obj = dmsCacheService.get("dmsCache", "DBInfo"+dbBaseId);
//		}
//		if (obj != null) {
//			return (DbBaseInfoVO) obj; 
//		}
//		throw ExceptionHandler.publish("", "获取数据库信息失败，请检查数据库信息是否配置|DB_BASE_ID="+dbBaseId);
		return dbBaseInfo;
	}
	
	@Override
	public DbLinkInstanceVO queryDBInstance(Integer dbLinkId) throws BaseAppException {
		DbLinkInstanceVO dbLinkInstanceVO = (DbLinkInstanceVO) dmsCacheService.get("dmsCache", "DBInstanceInfo"+dbLinkId);
		return dbLinkInstanceVO;
	}
	
	/**
	 * 数据库连接用户信息——公共查询方法
	 */
	public DbUserInfoVO queryDBInfo(Integer dbLinkId, String dbUserName) throws BaseAppException {
		Object obj = dmsCacheService.get("dmsCache", "DbUserInfo"+dbLinkId+dbUserName);
//		if (obj == null) {
//			addDBBaseInfo(dbLinkId);
//			obj = dmsCacheService.get("dmsCache", "DBInstanceInfo"+dbLinkId+dbUserName);
//		}
//		if (obj != null) {
//			return (DbUserInfoVO) obj;
//		}
//		throw ExceptionHandler.publish("", "获取数据库连接用户信息失败，请检查数据库用户信息|DB_BASE_ID="+
//				dbLinkId+",DB_USER_NAME="+dbUserName);
		return (DbUserInfoVO) obj;
	}

	/**
	 * 主机信息、连接方式——公共查询方法
	 */
	public HostConnInfoVO queryHostConn(Integer hostId) throws BaseAppException {
		Object obj = dmsCacheService.get("dmsCache", "HostInfo"+hostId);
		if (obj == null) {
			addHostBaseInfo(hostId);
			obj = dmsCacheService.get("dmsCache", "HostInfo"+hostId);
		}
		if (obj != null) {
			return (HostConnInfoVO) obj; 
		}
		throw ExceptionHandler.publish("", "获取主机信息失败，请检查数据库信息是否配置|HOST_ID="+hostId);
	}
	
	/**
	 * 主机信息、连接方式——公共查询方法
	 */
	@Override
	public HostConnInfoVO getHostConn(String ip) {
		Object obj = dmsCacheService.get("dmsCache", "HostInfo"+ip);
		if (obj == null) {
			return null;
		}
		return (HostConnInfoVO) obj; 
	}
	
	@Override
	public HostConnInfoVO qryHostConn(Integer dbLinkId) throws BaseAppException {
		try {			
			DbLinkInstanceVO dbLinkInstanceVO = (DbLinkInstanceVO) dmsCacheService.get("dmsCache", "DBInstanceInfo"+dbLinkId);
			DbBaseInfoVO dbBaseInfoVO = (DbBaseInfoVO) dmsCacheService.get("dmsCache", "DbBaseInfo"+dbLinkInstanceVO.getDbBaseId());
			DmHostConnInfoArg connInfoArg = new DmHostConnInfoArg();
			DmHostConnInfoArg.DmHostConnInfoCriteria connInfoCriteria = connInfoArg.createCriteria();
			connInfoCriteria.andIpEqualTo(dbBaseInfoVO.getDbHostIp());
			List<DmHostConnInfoPO> tempList = dmHostConnInfoDao
					.selectByArg(connInfoArg);
			if (Utils.notEmpty(tempList)) {
				return queryHostConn(tempList.get(0).getHostId());
			}
			return null;
		} catch (Exception e) {
			LOGGER.error("获取主机信息配置异常",e);
			throw ExceptionHandler.publish("获取主机信息配置异常",e);
		}
	}
	
	/**
	 * 数据库信息配置
	 * @see com.ztesoft.web.syncbaseinfo.service.BaseInfoService#getDbConfig(java.lang.Integer, java.lang.String)
	 * @return {数据库类型，数据库连接，用户名，密码}
	 * modified by lin.wb add 数据库名~
	 */
	public String[] getDbConfig(Integer dbLinkId, String dbUserName) throws BaseAppException {
		try {			
			DbLinkInstanceVO dbLinkInstanceVO = (DbLinkInstanceVO) dmsCacheService.get("dmsCache", "DBInstanceInfo"+dbLinkId);
			DbBaseInfoVO dbBaseInfoVO = (DbBaseInfoVO) dmsCacheService.get("dmsCache", "DbBaseInfo"+dbLinkInstanceVO.getDbBaseId());
			DbUserInfoVO dbUserInfoVO = (DbUserInfoVO)dmsCacheService.get("dmsCache", "DbUserInfo"+dbLinkId+dbUserName);
			
			String connURL = Util.bldConnURL(dbBaseInfoVO.getDbCategory().toLowerCase(), 
					dbBaseInfoVO.getDbHostIp(), dbBaseInfoVO.getDbHostPort(), dbBaseInfoVO.getDbName(), 
					dbLinkInstanceVO.getDbLinkName(),dbLinkInstanceVO.getDbLinkParam());
			String[] dbConfig = new String[]{dbBaseInfoVO.getDbCategory().toLowerCase(),
					connURL, dbUserName, RSAUtils.decryptString(dbUserInfoVO.getDbPassword()), 
					dbLinkInstanceVO.getDbLinkName()};//add 数据库名
//			LOGGER.debug("数据库信息："+(dbConfig[0]+","+dbConfig[1]+","+dbConfig[2]+","+dbConfig[3]));
			return dbConfig;
		} catch (Exception e) {
			String errMsg = StringUtils.format("获取数据库信息配置异常dbLinkId:[{0}],dbUserName:[{1}]", dbLinkId, dbUserName);
			LOGGER.error(errMsg,e);
			throw ExceptionHandler.publish(ErrorCode.LOCKUP_DB_CONFIG_ERROR, e, dbLinkId+"", dbUserName);
		}
	}
	
	
	/**
	 * 外部监测接收暂停、取消判断处理
	 */
	@Override
	public String doCheck(DmTaskStageDto taskStagePO, DmPlanPO planPO) {
		TaskNotify notify =  DMSConstant.taskInstList.get(taskStagePO.getDmTaskId());
		String code = notify.getStatus();//异常编码
		String msg = notify.getDealDesc();//异常信息
		if(DMSConstant.Status.PAUSE.toString().equals(code)||DMSConstant.Status.SYSPAUSE.toString().equals(code)){
			if (taskStagePO.getStage() == 0) {
				taskStagePO.setState("00A");
				taskStagePO.setTaskStartTime(null);
				taskStagePO.setTaskEndTime(DateUtils.getNowDate());
				/*
				 * 判断是否需要子任务
				 */
				if ("1".equals(planPO.getExecType())) {				
					DmTaskPO record = new DmTaskPO();
					DmTaskArg arg = new DmTaskArg();
					record.setNeedSubtask(DMSConstant.NEED_SUBTASK_T);
					DmTaskArg.DmTaskCriteria criteria = arg.createCriteria();
				    criteria.andDmTaskIdEqualTo(taskStagePO.getDmTaskId());
					taskDao.updateByArgSelective(record, arg);
				}
			} else if (taskStagePO.getStage() == 2) {
				if ((DMSConstant.Status.SYSPAUSE.toString().equals(code) 
						&& notify.getDealType().equals("TBS_USED"))) {
					return null;//清理环节~；；；；表空间的系统暂停不理睬
				}
				taskStagePO.setState("00T");
				taskStagePO.setTaskEndTime(null);
			}
		    taskStagePO.setStateDate(DateUtils.getNowDate());
		    taskStagePO.setErrorDesc(msg);
		    taskStagePO.setTaskStartTime(null);
		    taskStagePO.setCheckDataSize(null);
			taskStageCustomDao.updateTaskStageState(taskStagePO);//
			return code;
		}else if(DMSConstant.Status.CANCEL.toString().equals(code)){
			if (taskStagePO.getStage() != 2) {
				taskStagePO.setState("00X");
				taskStagePO.setStateDate(DateUtils.getNowDate());
				taskStagePO.setErrorDesc(msg);
				taskStagePO.setTaskStartTime(null);
				taskStagePO.setTaskEndTime(DateUtils.getNowDate());
				if (taskStagePO.getStage() == 0) taskStagePO.setStage(null);
				taskStageCustomDao.updateTaskStageState1(taskStagePO);//
				return "00C";
			} else {
				return null;
			}
		} else {
			return null;
		}
	}
	
}
